﻿using BlazorAdmin.Interface;
using BlazorAdmin.Models;
using BlazorAdmin.Web.Shared.Models;
using BlazorAdmin.Web.Shared.Services;
using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Pangeo.Admin.Models;
using System.IO.Compression;

namespace BlazorAdmin.Web.Shared.Pages.Admin
{
    public partial class FileManager
    {
        private List<TreeViewItem<FileDirInfo>> FileDirTree { get; set; }

        public FileDirInfo SelectedFileDir { get; set; }

        private TreeView<FileDirInfo> FileTree { get; set; }

        private string NewDirName { get; set; }

        private DialogOption Option { get; set; }

        private string? SelectedOrgCode { get; set; }

        private List<TreeViewItem<Organize>>? OrganizeTree { get; set; }

        /// <summary>
        /// 单个文件最大100MB，超过则无法上传
        /// </summary>
        private long MaxFileLength => 100 * 1024 * 1024;

        protected override async Task OnInitializedAsync()
        {
            FileDirTree = new List<TreeViewItem<FileDirInfo>>();
            OrganizeTree = await OrganizeService?.GetOrganizeTree(AppContext?.LoginName);

            // 默认选中未分组
            OrganizeTree[0].CheckedState = CheckboxState.Checked;
            SelectedOrgCode = OrganizeTree[0].Value.OrgCode;

            RefreshDirTree();
        }

        /// <summary>
        /// 获取根目录下所有子目录信息
        /// </summary>
        private Task RefreshDirTree()
        {
            var fileBackupPath = Consts.BackupFilesPath;

            if (Directory.Exists(fileBackupPath))
            {
                var query = new AppQueryOption<string>(AppContext?.LoginName);
                query.Param = SelectedOrgCode; // 查询未分组、已分组的
                var devices = DeviceService?.Query(query).Result.Items.ToList();
                if (devices == null || devices.Count() == 0) // 没有设备
                {
                    FileDirTree.Clear();
                    return Task.CompletedTask;
                }

                // 递归遍根目录
                var rootDir = new TreeViewItem<FileDirInfo>(new() { Path = fileBackupPath });
                FileDirTree = rootDir.Items;

                RecurseDirGenTree(new DirectoryInfo(fileBackupPath), rootDir, devices);
            }
            else
            {
                Directory.CreateDirectory(fileBackupPath);
                FileDirTree = new List<TreeViewItem<FileDirInfo>>();
            }

            return Task.CompletedTask;
        }

        private void RecurseDirGenTree(DirectoryInfo directory, TreeViewItem<FileDirInfo> dirData, List<Device> devices)
        {
            dirData.Text = directory.Name;
            if (Consts.BackupFilesPath == directory.Parent?.FullName && dirData.Text.Length == 32)
            {
                var dev = devices.FirstOrDefault(t => t.Guid == dirData.Text);
                if (dev == null)
                {
                    FileDirTree.Remove(dirData);
                    return;
                }

                if (!string.IsNullOrEmpty(dev.AssetNo))
                    dirData.Text = $"{dev.AssetNo}（{dev.IP}）";
                else
                    dirData.Text = dev.IP;
            }

            // 获取当前目录下的文件
            foreach (var file in directory.GetFiles())
            {
                dirData.Items.Add(new TreeViewItem<FileDirInfo>(new() { Path = file.FullName.Replace("\\", "/") }) { 
                    Text = $"{file.Name}（ {DescriptFileSize(file.Length)} ，{file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")} ）",
                    Icon = "fas fa-file"
                });
            }

            // 遍历当前目录下的子目录
            foreach (var subDir in directory.GetDirectories())
            {
                dirData.Items.Add(new TreeViewItem<FileDirInfo>(new() { Path = subDir.FullName.Replace("\\", "/"), IsDirectory = true }) { 
                    Text = subDir.Name,
                    Icon = "fas fa-folder",
                    ExpandIcon = "fas fa-folder-open"
                });

                RecurseDirGenTree(subDir, dirData.Items[dirData.Items.Count - 1], devices);
            }

            // 遍历完后，按时间倒叙排列
            dirData.Items = dirData.Items.OrderByDescending(t => t.Text).ToList();
        }

        private string DescriptFileSize(long length)
        {
            if(length < 1024)
                return length + "B";
            else if(length / 1024 < 1024)
                return (length / 1024).ToString("#.##") + "KB";
            else
                return (length / (1024 * 1024)).ToString("#.##") + "MB";
        }

        private async Task OnTreeItemChecked(TreeViewItem<FileDirInfo> items)
        {
            SelectedFileDir = items.Value;
        }

        private async Task CreateDirectory()
        {
            Option = new DialogOption()
            {
                Title = "创建目录",
                Size = Size.Small,
                BodyTemplate = BootstrapDynamicComponent.CreateComponent<BootstrapInput<string>>(new Dictionary<string, object?>
                {
                    [nameof(BootstrapInput<string>.Value)] = NewDirName,
                    [nameof(BootstrapInput<string>.PlaceHolder)] = "请输入目录名称",
                    [nameof(BootstrapInput<string>.ValueChanged)] = EventCallback.Factory.Create<string>(this, v => NewDirName = v)
                }).Render(),
                FooterTemplate = BootstrapDynamicComponent.CreateComponent<Button>(new Dictionary<string, object?>
                {
                    [nameof(Button.Color)] = Color.Primary,
                    [nameof(Button.Text)] = "确认",
                    [nameof(Button.Icon)] = "fa-solid fa-fw fa-check",
                    [nameof(Button.OnClick)] = EventCallback.Factory.Create<MouseEventArgs>(this, async () =>
                    {
                        if (!string.IsNullOrWhiteSpace(NewDirName))
                        {
                            var path = Consts.BackupFilesPath; // 默认在根目录下创建
                            if (SelectedFileDir != null)
                            {
                                path = SelectedFileDir.Path;
                                if (!SelectedFileDir.IsDirectory)
                                    path = SelectedFileDir.Path.Substring(0, SelectedFileDir.Path.LastIndexOf("/"));
                            }

                            try
                            {
                                path += "/" + NewDirName.Trim();
                                if (Directory.Exists(path))
                                {
                                    MsgService?.Show(new()
                                    {
                                        Icon = "fa-solid fa-circle-info",
                                        Content = $"创建失败，已存在{NewDirName.Trim()}该目录",
                                        Color = Color.Danger
                                    });
                                    return;
                                }

                                Directory.CreateDirectory(path);

                                NewDirName = string.Empty;
                            }
                            catch (Exception ex)
                            {
                                MsgService?.Show(new()
                                {
                                    Icon = "fa-solid fa-circle-info",
                                    Content = $"{AppDomain.CurrentDomain.BaseDirectory}，创建失败，{ex.ToString()}",
                                    Color = Color.Danger
                                });
                                return;
                            }

                            RefreshDirTree();

                            Option?.CloseDialogAsync();
                        }
                    }),
                }).Render()
            };

            _ = DialogService?.Show(Option);
        }

        private async Task UploadFile(UploadFile file)
        {
            var filePath = Consts.BackupFilesPath;
            if (SelectedFileDir != null)
            {
                if (SelectedFileDir.IsDirectory)
                    filePath = SelectedFileDir.Path;
                else
                    filePath = SelectedFileDir.Path.Substring(0, SelectedFileDir.Path.LastIndexOf("/"));
            }
            filePath += "/" + file.OriginFileName;

            _ = file.SaveToFileAsync(filePath, MaxFileLength);
        }

        private async Task DownloadFile()
        {
            if (SelectedFileDir == null)
            {
                MsgService?.Show(new() { Content = "请选择要下载的文件或目录" });
                return;
            }

            var fileName = SelectedFileDir.Path.Substring(SelectedFileDir.Path.LastIndexOf("/") + 1);
            if (SelectedFileDir.IsDirectory) // 如果选择目录，则打包下载
            {
                fileName += ".zip";
                var timeFilePath = $"{Consts.BackupFilesPath}/{DateTime.Now.ToString("yyMMddHHmmss")}";
                var zipfilePath = $"{timeFilePath}/{fileName}";

                Directory.CreateDirectory(timeFilePath);

                ZipFile.CreateFromDirectory(SelectedFileDir.Path, zipfilePath);

                if (File.Exists(zipfilePath))
                {
                    using (var stream = new FileStream(zipfilePath, FileMode.Open))
                        await DownloadService?.DownloadFromStreamAsync(fileName, stream);

                    Directory.Delete(timeFilePath, true);
                }
                else
                {
                    MsgService?.Show(new() { Content = "下载失败，无法创建压缩包", Color = Color.Danger });
                }
            }
            else
            {
                using (var stream = new FileStream(SelectedFileDir.Path, FileMode.Open))
                    await DownloadService?.DownloadFromStreamAsync(fileName, stream);
            }
        }

        private async Task DeleteFile()
        {
            if (SelectedFileDir == null)
            {
                MsgService?.Show(new() { Content = "请选择要删除的文件或目录" });
                return;
            }

            try
            {
                if (SelectedFileDir.IsDirectory) // 删除指定目录及其所有文件
                    Directory.Delete(SelectedFileDir.Path, true);
                else
                    File.Delete(SelectedFileDir.Path);

                MsgService?.Show(new()
                {
                    Content = "删除成功！"
                });
            }
            catch (Exception ex)
            {
                MsgService?.Show(new()
                {
                    Icon = "fa-solid fa-circle-info",
                    Content = $"删除失败，{ex.ToString()}",
                    Color = Color.Danger
                });
            }

            RefreshDirTree();

            InvokeAsync(StateHasChanged);
        }

        private Task OnOrganizeClick(TreeViewItem<Organize> item)
        {
            if (SelectedOrgCode != item.Value.OrgCode) // 发生改变之后，重新查询
            {
                SelectedOrgCode = item.Value.OrgCode;

                RefreshDirTree();
                StateHasChanged();
            }

            return Task.CompletedTask;
        }

        #region Inject 注入的服务

        [Inject]
        private BootstrapAppContext? AppContext { get; set; }

        [Inject]
        private DialogService? DialogService { get; set; }

        [Inject]
        private MessageService? MsgService { get; set; }

        [Inject]
        private DownloadService? DownloadService { get; set; }

        [Inject]
        private IOrganize? OrganizeService { get; set; }

        [Inject]
        private IDevice? DeviceService { get; set; }

        #endregion
    }
}
